using AvaVSExt.Attributes;
using AvaVSExt.Helpers;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace AvaVSExt
{
    public partial class Program
    {
        [VSCommand("gotocode")]
        public static void RunGotoCode()
        {
            var selection = VSHelper.GetCurrentSelectLineText();
            if (selection is null) return;
            var xamlClass = GotoCode.ParseXamlClass(selection);
            if (xamlClass is null) return;

            var slnDir = VSHelper.GetSlnDir();
            var pattern = $"{xamlClass.ClassName}.*cs";

            var files = FileSystemHelper.GetFiles(slnDir, pattern);
            var fileDates = files.Select(i => (i, File.GetLastWriteTime(i)));
            var fileDate = fileDates.OrderByDescending(i => i.Item2).FirstOrDefault();

            VSHelper.Open(fileDate.i);
            //VSHelper.Test();
        }
    }

    public class XamlClass
    {
        public string NamespaceShortName { get; set; }
        public string ClassName { get; set; }
    }

    public class GotoCode
    {
        public static XamlClass ParseXamlClass(VSHelper.SelectionLineInfo selectionLineInfo)
        {
            if (selectionLineInfo is null) return null;

            var colonType = GetColonType(selectionLineInfo);

            var typeName = GetTypeNameFromColonType(colonType);

            if (string.IsNullOrWhiteSpace(typeName)) return null;

            return new XamlClass() { ClassName = typeName };
        }

        private static string GetColonType(VSHelper.SelectionLineInfo selectionLineInfo)
        {
            var colonsIndexs = GetColons(selectionLineInfo.Text);

            foreach (var colonsIndex in colonsIndexs)
            {
                var colonsContext = GetColonContext(selectionLineInfo, colonsIndex);
                if (IsType(colonsContext)) return colonsContext;
            }

            return string.Empty;
        }

        private static string GetColonContext(VSHelper.SelectionLineInfo selectionLineInfo, int colonsIndex)
        {
            var prevIndex = SeekPrev(selectionLineInfo.Text, colonsIndex);
            var nextIndex = SeekNext(selectionLineInfo.Text, colonsIndex);

            var textLine = selectionLineInfo.Text.Substring(prevIndex + 1, nextIndex - prevIndex - 1);
            return textLine;
        }

        private static bool IsType(string colonsContext)
        {
            var colons = ':';
            var colonsIndex = colonsContext.IndexOf(colons);

            if (colonsIndex < 0) return false;
            var prevPart = colonsContext.Substring(0, colonsIndex);
            //var nextPart = colonsContext.Substring(colonsIndex);
            var ignores = new string[]
            {
                "x", "xmlns","d", "mc", "using"
            };

            return ignores.All(i => i != prevPart);
        }

        private static string GetTypeNameFromColonType(string colonType)
        {
            var colons = ':';
            var colonsIndex = colonType.IndexOf(colons);
            var nextPart = colonType.Substring(colonsIndex + 1);
            return nextPart;
        }


        public static int[] GetColons(string text)
        {
            var list = new List<int>();
            var colons = ':';
            for (int i = 0; i < text.Length; i++)
            {
                var ch = text[i];
                if (ch == ':') list.Add(i);
            }
            return list.ToArray();
        }

        private static int SeekPrev(string text, int colonsIndex)
        {
            for (int i = colonsIndex; i >= 0; i--)
            {
                var ch = text[i];
                if (IsSpecialChar(ch)) return i;
            }
            return 0;
        }
        private static int SeekNext(string text, int colonsIndex)
        {
            for (int i = colonsIndex; i < text.Length; i++)
            {
                var ch = text[i];
                if (IsSpecialChar(ch)) return i;
            }
            return text.Length;
        }

        private static bool IsSpecialChar(char ch)
        {
            if (ch == ' ') return true;
            if (ch == '<') return true;
            if (ch == '>') return true;
            if (ch == '/') return true;
            if (ch == '\\') return true;
            if (ch == '=') return true;
            if (ch == '"') return true;
            return false;
        }
    }
}
